//#include <SPI.h>

#define _SPI_CMDType_Send 1
#define _SPI_CMDType_Receive 2
#define pinMISO 3

volatile uint8_t _SPI_DataCount = 0;
volatile uint8_t _SPI_DataSize = 0;
volatile uint8_t _SPI_CurrentCommand = 0;
volatile int _SPI_DataStructure;
volatile uint8_t _SPI_CMDType;

void SPISlaveSetup()
{
  DDRB |= (1<<pinMISO); //set MISO pin as output
  SPCR |= _BV(SPE);  // turn on SPI in slave mode
  SPCR |= _BV(SPIE); // turn on interrupts
} 

ISR (SPI_STC_vect)
{
  uint8_t SPIDataIn = SPDR;
      
  if (!_SPI_DataCount) //get command
  {
    _SPI_CommandSelect()
  } 
  else // the rest of the data
  {
    switch (_SPI_CMDType)  
    {
    case _SPI_CMDType_Send:
      _SPI_Slave_Send();
      break;
          
    case _SPI_CMDType_Receive:
      _SPI_Slave_Receive();
      break;
    }
  }

  _SPI_DataCount++;
      
  if (_SPI_DataCount > _SPI_DataSize) //if there is no more data to get then reset ready for next command
  {
    _SPI_DataCount = 0;
    _SPI_DataSize = 0;
  }
}

  
void _SPI_CommandSelect()
{
    switch (SPIDataIn) //select data and command
    {
    case SPICMD_REQUEST_BUTTONDATA:
      _SPI_DataStructure = &buttonData;
      _SPI_Slave_Send();
  	  break;

    case SPICMD_REQUEST_LINEDATA:
      _SPI_DataStructure = &lineSensorData;
      _SPI_Slave_Send();
  	  break;

    case SPICMD_REQUEST_RF_STRING:
      _SPI_DataStructure = &RFInString;
      _SPI_Slave_Send();
      break;
      
    case SPICMD_REQUEST_WALLDATA:
      _SPI_DataStructure = &wallSensorData;
      _SPI_Slave_Send();
      break;

    case SPICMD_SEND_LEDDATA:
      _SPI_DataStructure = &LEDData;
      _SPI_Slave_Receive();
      break;
      
    case SPICMD_SEND_OLED_STRING:
      _SPI_DataStructure = &OLEDString;
      _SPI_Slave_Receive();
      break;
      
    case SPICMD_SEND_RF_STRING:
      _SPI_DataStructure = &RFOutString;
      _SPI_Slave_Receive();
      break;
      
    }
}

_SPI_Slave_Send()
{
      if (!_SPI_DataCount)
      {
        _SPI_CMDType = _SPI_CMDType_Send;
        _SPI_CurrentCommand = SPIDataIn;
        _SPI_DataSize = sizeof(*_SPI_DataStructure);
        SPDR = _SPI_DataSize
      }
      else
      {
        SPDR = *(_SPI_DataStructure + _SPI_DataCount -1)
      }
}

void _SPI_Slave_Receive()
{
    switch(_SPI_DataCount)
    {
      case 0:
        _SPI_CMDType = _SPI_CMDType_Receive;
        _SPI_CurrentCommand = SPIDataIn;
        _SPI_DataSize = 1; //we are expecting one more byte before we get the data structure
      break;
      case 1:
        _SPI_DataSize = SPIDataIn;
      break;
      default:
         *(_SPI_DataStructure + _SPI_DataCount -1) = SPIDataIn;
      break;
    }
}

